package com.hq.zb.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.hq.zb.dto.MenuDto;
import com.hq.zb.entity.CurrentUser;
import com.hq.zb.exception.BizException;
import com.hq.zb.exception.BizExceptionEnum;
import com.hq.zb.mapper.MenuMapper;
import com.hq.zb.mapper.RoleMenuMapper;
import com.hq.zb.mapper.UserMenuMapper;
import com.hq.zb.model.Menu;
import com.hq.zb.model.UserMenu;
import com.hq.zb.service.IMenuService;
import com.hq.zb.vo.CommTreeVo;
import com.hq.zb.vo.MenuTreeVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author huanghanrui
 * @since 2022-03-08
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Autowired
    private UserMenuMapper userMenuMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public List<CommTreeVo> queryTree(MenuDto menuDto) {
        Wrapper<Menu> wrapper = new EntityWrapper<>();
        wrapper.eq("delete_flag", false);
        wrapper.eq("sys_source", menuDto.getSysSource());
        List<Menu> menus = menuMapper.selectList(wrapper);
        List<Menu> menuList = menus.stream().filter(x -> x.getParentMenu() == null || x.getParentMenu() == 0).collect(Collectors.toList());
        // 为一级菜单设置子菜单，getChild是递归调用的
        List<CommTreeVo> commTreeVos = new ArrayList<>();
        for (Menu menu : menuList) {
            CommTreeVo commTreeVo = new CommTreeVo();
            commTreeVo.setId(menu.getMenuId());
            commTreeVo.setLabel(menu.getMenuName());
            commTreeVo.setChildren(getMenuChild(menu.getMenuId(), menus));
            commTreeVos.add(commTreeVo);
        }
        return commTreeVos;
    }

    private List<CommTreeVo> getMenuChild(Integer menuId, List<Menu> menus) {
        // 子菜单
        List<CommTreeVo> childList = null;
        if (CollectionUtil.isNotEmpty(menus)) {
            List<Menu> menuList = menus.stream().filter(x->menuId.equals(x.getParentMenu())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(menuList)) {
                childList = new ArrayList<>();
                for (Menu menu : menuList) {
                    CommTreeVo commTreeVo = new CommTreeVo();
                    commTreeVo.setId(menu.getMenuId());
                    commTreeVo.setLabel(menu.getMenuName());
                    List<Menu> menuList1 = menus.stream().filter(x -> menu.getMenuId() == x.getParentMenu()).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(menuList1)) {
                        commTreeVo.setChildren(getMenuChild(menu.getMenuId(), menus));
                    }
                    childList.add(commTreeVo);
                }
            }
        }
        return childList;
    }

    @Override
    public List<MenuTreeVo> queryByCurrentUser(CurrentUser currentUser, String sysSource) {
        //查询角色菜单
        currentUser.setSysSource(sysSource);
        List<MenuTreeVo> menus = null;
        if ("admin".equals(currentUser.getUserName())) {
            menus = menuMapper.queryAllMenu();
        } else {
            List<Integer> menuIds = new ArrayList<>();
                    //判断用户是否分配了对立菜单，没有的默认角色菜单
            Wrapper<UserMenu> wrapper = new EntityWrapper<>();
            wrapper.eq("user_id", currentUser.getUserId());
            Integer count = userMenuMapper.selectCount(wrapper);
            if (count <= 0) {
                menuIds = roleMenuMapper.queryMenuIdByRoleUser(currentUser.getUserId());
            } else {
                menuIds = userMenuMapper.queryMenuIds(currentUser.getUserId());
            }
            if (CollectionUtil.isNotEmpty(menuIds)) {
                menus = menuMapper.queryByMenuIds(menuIds);
            }
        }
        // 为一级菜单设置子菜单，getChild是递归调用的
        List<MenuTreeVo> menuTreeVos = null;
        if (CollectionUtil.isNotEmpty(menus)) {
            //一级菜单
            List<MenuTreeVo> menuTree = menus.stream().filter(x -> StringUtils.isBlank(x.getParentMenu())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(menuTree)) {
                menuTreeVos = new ArrayList<>();
                for (MenuTreeVo menuTreeVo : menuTree) {
                    menuTreeVo.setTitle(menuTreeVo.getMenuName());
                    menuTreeVo.setIndex(menuTreeVo.getMenuId().toString());
                    if (StringUtils.isNotEmpty(menuTreeVo.getMenuPath())) {
                        menuTreeVo.setIndex(menuTreeVo.getMenuPath());
                    }
                    menuTreeVo.setChildren(getChild(menuTreeVo.getMenuId().toString(), menus));
                    menuTreeVos.add(menuTreeVo);
                }
            }
        }
        return menuTreeVos;
    }

    /**
     * 递归查找子菜单
     * @param menuId
     * @param menus
     */
    private List<MenuTreeVo> getChild(String menuId, List<MenuTreeVo> menus) {
        // 子菜单
        List<MenuTreeVo> childList = new ArrayList<>();
        for (MenuTreeVo menuTreeVo : menus) {
            // 遍历所有节点，将父菜单id与传过来的id比较
            if (StringUtils.isNotEmpty(menuTreeVo.getParentMenu())) {
                if (menuTreeVo.getParentMenu().equals(menuId)) {
                    menuTreeVo.setIndex(menuTreeVo.getMenuId().toString());
                    if (StringUtils.isNotEmpty(menuTreeVo.getMenuPath())) {
                        menuTreeVo.setIndex(menuTreeVo.getMenuPath());
                    }
                    menuTreeVo.setTitle(menuTreeVo.getMenuName());
                    childList.add(menuTreeVo);
                }
            }
        }
        // 把子菜单的子菜单再循环一遍
        for (MenuTreeVo menuTreeVo : childList) {// 没有url子菜单还有子菜单
            if (StringUtils.isBlank(menuTreeVo.getMenuPath())) {
                // 递归
                menuTreeVo.setChildren(getChild(menuTreeVo.getMenuId().toString(), menus));
            }
        } // 递归退出条件
        if (childList.size() == 0) {
            return null;
        }
        return childList;
    }

    @Override
    public void saveMenu(Menu menu) {
        if (StringUtils.isBlank(menu.getMenuName())) {
            //菜单名称必填
            throw new BizException(BizExceptionEnum.DATA_NOT_NULL, "菜单名称必填.");
        }
        if (menu.getSortNumber() == null) {
            menu.setSortNumber(0);
        }
        menu.setEnableFlag(true);
        if (menu.getMenuId() == null) {
            this.insert(menu);
        } else {
            this.updateById(menu);
        }
    }

    /**
     * 获取下下级菜单
     * @param menuId
     * @param menuIds
     */
    @Override
    public  void getSubordinateMenus(Integer menuId, List<Integer> menuIds) {
        Wrapper<Menu> wrapper = new EntityWrapper<>();
        wrapper.eq("delete_flag", false);
        wrapper.eq("parent_menu", menuId);
        List<Menu> menus = this.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(menus)) {
            for (Menu menu : menus) {
                menuIds.add(menu.getMenuId());
                getSubordinateMenus(menu.getMenuId(), menuIds);
            }
        }
    }

    /**
     * 获取上级上上级菜单
     * @param menuId
     * @param menuIds
     */
    @Override
    public  void getHigherLevelMenus(Integer menuId, Set<Integer> menuIds) {
        Wrapper<Menu> wrapper = new EntityWrapper<>();
        wrapper.eq("delete_flag", false);
        wrapper.eq("menu_id", menuId);
        List<Menu> menus = this.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(menus)) {
            for (Menu menu : menus) {
                menuIds.add(menu.getMenuId());
                if (menu.getParentMenu() != null) {
                    getHigherLevelMenus(menu.getParentMenu(), menuIds);
                }
            }
        }
    }

    @Override
    public void deleteMenu(List<Menu> menus) {
        if (CollectionUtil.isNotEmpty(menus)) {
            for (Menu menuDto : menus) {
                menuDto.setDeleteFlag(true);
                menuMapper.updateById(menuDto);
            }
        }
    }

    @Override
    public Page<MenuTreeVo> queryMenu(Page<MenuTreeVo> page, Wrapper<MenuTreeVo> wrapper) {
        page.setRecords(menuMapper.queryMenu(page, wrapper));
        return page;
    }
}
